// --------------------------------------------------------------------------------------------------------------------
// <copyright file="OnPremisesAdapter.cs" company="">
//   
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace ExecutionTool.CopyOnPremises
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;

    using ExecutionTool.Common;
    using ExecutionTool.Profile;

    using Microsoft.Practices.EnterpriseLibrary.Logging;
    using Microsoft.Practices.ServiceLocation;

    public class OnPremisesAdapter : IOnPremisesAdapter
    {
        #region Constants

        private const string AdsMetadataName = "SqlAzureDataProtector.metadata";

        #endregion

        #region Fields

        private readonly LogWriter logger;

        #endregion

        #region Constructors and Destructors

        public OnPremisesAdapter(LogWriter logger = null)
        {
            this.logger = logger ?? ServiceLocator.Current.GetInstance<LogWriter>();
        }

        #endregion

        #region Public Methods and Operators

        public double GetFileSizeInBytes(string filePath)
        {
            this.logger.LogVerbose(string.Format("Getting on-premises file size [{0}]...", filePath));

            var info = new FileInfo(filePath);
            var size = info.Length;

            this.logger.LogVerbose(string.Format("Got on-premises file size [{1}B] of [{0}].", filePath, size));

            return size;
        }

        public Dictionary<string, string> GetMetadata(string filePath)
        {
            this.logger.LogVerbose(string.Format("Getting metadata for file [{0}]...", filePath));

            var stream = AdsFile.Read(filePath, AdsMetadataName);
            var lines = stream.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

            var builder = new StringBuilder();
            var metadata = new Dictionary<string, string>();
            foreach (var pair in lines.Select(line => line.Split(new[] { '\t' }, StringSplitOptions.None)))
            {
                builder.Append(string.Format("{0}:{1};", pair[0], pair[1]));
                metadata.Add(pair[0], pair[1]);
            }

            this.logger.LogVerbose(string.Format("Got metadata [{1}] for file [{0}].", filePath, builder));

            return metadata;
        }

        public IEnumerable<FileInfo> ListBlobs(string folderPath)
        {
            this.logger.LogVerbose(string.Format("Listing files in folder [{0}]...", folderPath));

            var files = Directory.GetFiles(folderPath);

            this.logger.LogVerbose(string.Format("Listed [{1}] files in folder [{0}]...", folderPath, files.Length));

            return files.Select(file => new FileInfo(file)).ToList();
        }

        public void SetMetadata(string filePath, Dictionary<string, string> metadata)
        {
            this.logger.LogVerbose(string.Format("Setting metadata for file [{0}]...", filePath));

            var builder = new StringBuilder();
            var builder2 = new StringBuilder();
            foreach (var pair in metadata)
            {
                builder.Append(string.Format("{0}:{1};", pair.Key, pair.Value));
                builder2.Append(pair.Key).Append('\t').Append(pair.Value).AppendLine();
            }

            AdsFile.Write(builder2.ToString(), filePath, AdsMetadataName);

            this.logger.LogVerbose(string.Format("Set metadata [{1}] for file [{0}].", filePath, builder));
        }

        public void TestConnection(OnPremisesLocation targetOnPremisesLocation)
        {
            this.logger.LogVerbose(string.Format("Testing on-premises location [{0}]...", targetOnPremisesLocation.Location));

            if (!Directory.Exists(targetOnPremisesLocation.Location))
            {
                throw new StepFaultException(
                    string.Format("On-premises location [{0}] doesn't exist.", targetOnPremisesLocation.Location), 
                    StepType.TestConnection, 
                    ErrorCodes.CopyingToOnPremisesTestConnectionError);
            }

            this.logger.LogVerbose(string.Format("Tested on-premises location [{0}].", targetOnPremisesLocation.Location));
        }

        #endregion
    }
}
